//
// Unihan Input Method
//
// Copyright © 2002-2007 Sun Wah Linux Ltd.
//
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//
// $Id: unihan_xaux_so.c 806 2007-08-01 05:29:51Z roger $
//

#include <stdio.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "xaux_object.h"

#ifdef USE_AUX_IF_VERSION_2
#include "imbean.h"
#endif

#define MAX_NUM_AUX_MODULES  4
#define MAX_LEN_CLASS_NAME   128

#define ATOM_NUM_XAUX_MODULE 32

CARD16  utfname_xaux_object[] = {
        'c','o','m','.','s','w','-','l','i','n','u','x','.',
        'u','n','i','h','a','n','2','.',
        'a','u','x','.',
        'o','b','j','e','c','t',
};

CARD16  utfname_xaux_module_status[] = {
        'c','o','m','.','s','w','-','l','i','n','u','x','.',
        'u','n','i','h','a','n','2','.',
        'S','t','a','t','u','s','A','u','x',
};

CARD16  utfname_xaux_module_lookup[] = {
        'c','o','m','.','s','w','-','l','i','n','u','x','.',
        'u','n','i','h','a','n','2','.',
        'L','o','o','k','u','p','A','u','x',
};

xaux_class_t xaux_classes[MAX_NUM_AUX_MODULES] = {
	{
		XAUX_MODULE_STATUS_CLASS_NAME,  1,
		UNIHAN_XAUX_DIR "/gnome/xaux_ext_status",
		(Window)0, (Window)0, (Window)0,
		(Atom)0, (Atom)0, (Atom)0,  (Atom)0,
		{ (Atom)0 }, ATOM_NUM_XAUX_MODULE, 0, 
		{ (Atom)0 }, ATOM_NUM_XAUX_MODULE, 0,
		utfname_xaux_module_status,
	},
	{
		XAUX_MODULE_LOOKUP_CLASS_NAME,  2,
		UNIHAN_XAUX_DIR "/gnome/xaux_ext_lookup",
		(Window)0, (Window)0, (Window)0,
		(Atom)0, (Atom)0, (Atom)0,  (Atom)0,
		{ (Atom)0 }, ATOM_NUM_XAUX_MODULE, 0, 
		{ (Atom)0 }, ATOM_NUM_XAUX_MODULE, 0,
		utfname_xaux_module_lookup,
	},
	{
		NULL,  -1,
		NULL,
		(Window)0, (Window)0, (Window)0,
		(Atom)0, (Atom)0, (Atom)0,  (Atom)0,
		{ (Atom)0 }, 0, 0, 
		{ (Atom)0 }, 0, 0,
		(CARD16 *)NULL,
	},
};

extern aux_method_t xaux_so_methods;

aux_dir_t aux_dir[MAX_NUM_AUX_MODULES] = {
	{
		{ sizeof(utfname_xaux_object),
		  (CARD16 *)utfname_xaux_object,
		},
		&xaux_so_methods,
	},
	{
		{ sizeof(utfname_xaux_module_status),
		  (CARD16 *)utfname_xaux_module_status,
		},
		&xaux_so_methods,
	},
	{
		{ sizeof(utfname_xaux_module_lookup),
		  (CARD16 *)utfname_xaux_module_lookup,
		},
		&xaux_so_methods,
	},
	{ {0, NULL}, NULL},
};

int aux_classes_print(xaux_class_t *aux_classes)
{
#ifdef DEBUG
	xaux_class_t *p;

	if (aux_classes == NULL) return (AUX_OK);

	printf("\nxaux_classes: \n");
	for (p=aux_classes; p->classname; p++) {
		printf("class_name: %s, exec: %s\n", p->classname, p->extexec);
	}

	return (AUX_OK);
#endif
}

#ifdef USE_AUX_IF_VERSION_2

#define XAUX_MODULES_FILE "unihan_aux_modules.xml"

CARD16 utfname_aux_modules_custom[MAX_NUM_AUX_MODULES][MAX_LEN_CLASS_NAME];
char classname_aux_modules_custom[MAX_NUM_AUX_MODULES][MAX_LEN_CLASS_NAME];
char exec_aux_modules_custom[MAX_NUM_AUX_MODULES][MAX_LEN_CLASS_NAME];

int aux_dir_print(aux_dir_t *aux_dir)
{
#ifdef DEBUG
	aux_dir_t *p;

	if (aux_dir == NULL) return (AUX_OK);

	printf("\naux_dir: \n");
	for (p=aux_dir; p->name.ptr; p++) {
		char *class_name = NULL;
		class_name = (char *)xaux_so_get_classname_from_utfname(p->name.ptr, p->name.len);
		if (class_name) {
			printf("class_name: %s, len: %d\n", class_name, p->name.len);
			free ((char *)class_name);
		}
	}

	return (AUX_OK);
#endif
}

char *aux_dir_get_full_file_path(char *file_path)
{
	int len;
	char *full_file_path = NULL;

	if (!file_path || !*file_path)
		return (NULL);

	if (file_path[0] == '/') {
		len = strlen (file_path);

		full_file_path = (char *)calloc(len + 1, sizeof(char));
		if (full_file_path == NULL) return (NULL);

		snprintf(full_file_path, len + 1, "%s", file_path);
	} else {
		len = strlen(UNIHAN_XAUX_DIR) + 1 + strlen (file_path);

		full_file_path = (char *)calloc(len + 1, sizeof(char));
		if (full_file_path == NULL) return (NULL);

		snprintf(full_file_path, len + 1, "%s/%s", UNIHAN_XAUX_DIR, file_path);
	}

	return (full_file_path);
}

int aux_dir_get_custom_aux_modules(char *aux_dir_config_file)
{
#define AUX_MODULE_CLASS_NAME  "class_name"
#define AUX_MODULE_OBJECT_FILE "object_file"

	aux_dir_t *dir;
	int num_aux_dirs;
	int num_aux_dirs_custom;

	xaux_class_t *class;
	int num_aux_classes;
	int num_aux_classes_custom;

	IbmlData *ibml_data;
	IbmlCategory    *ibml_category;
	IbmlElement     *ibml_element;
	IbmlProperty    *ibml_property;
	int i, j, k, n;

	char *id, *scope;
	char *name, *value;

	num_aux_dirs = 0;
	for (dir=aux_dir; dir->name.ptr; dir++) num_aux_dirs++;

	num_aux_classes = 0;
	for (class=xaux_classes; class->classname; class++) num_aux_classes++;

	DEBUG_printf("num_aux_dirs: %d, num_aux_classes: %d\n", num_aux_dirs, num_aux_classes);
	ibml_data = (IbmlData *)imbean_config_new_from_file(aux_dir_config_file);
	if (ibml_data == NULL) return(AUX_FAIL);

	num_aux_classes_custom = 0;
	num_aux_dirs_custom = 0;
	for (k=0; k<ibml_data->num_categories; k++) {
		ibml_category = ibml_data->categories[k];

		if (ibml_category->scope == NULL) continue;
		if (! *ibml_category->scope) continue;
		if (strcasecmp(ibml_category->scope, "gtk2") && 
		    strcasecmp(ibml_category->scope, "qt") &&
		    strcasecmp(ibml_category->scope, "binary"))
			continue;

		for (i=0; i<ibml_category->num_elements; i++) {
			CARD16 *utfname_ptr;
			char *aux_module_class_name = NULL;
			char *aux_module_object_file = NULL;
			char *aux_module_file_path = NULL;

			ibml_element = ibml_category->elements[i];
			if (!ibml_element) continue;

			id = (char *)ibml_element->id;
			scope = (char *)ibml_element->scope;
			DEBUG_printf("id:%s, scope:%s\n", id?id:"NULL", scope?scope:"NULL");
			if (!id || !*id) continue;

			for(j=0; j<ibml_element->num_properties; j++) {
				ibml_property = ibml_element->properties[j];
				if (!ibml_property) continue;

				name = (char *)ibml_property->name;
				if (!name || !*name)
					continue;

				value = (char *)ibml_property->value;
				if (!value || !*value)
					continue;

				if (!strcasecmp(name, AUX_MODULE_CLASS_NAME)) {
					aux_module_class_name = value;
				} else if (!strcasecmp(name, AUX_MODULE_OBJECT_FILE)) {
					aux_module_object_file = value;
				}
			}

			if (!aux_module_class_name || !*aux_module_class_name)
				continue;
			if (!aux_module_object_file || !*aux_module_object_file)
				continue;

			DEBUG_printf("category: %s, classname: %s, object: %s\n",
				ibml_category->scope, aux_module_class_name, aux_module_object_file);

			if (num_aux_dirs + num_aux_dirs_custom >= MAX_NUM_AUX_MODULES-1)
				break;

			utfname_ptr = utfname_aux_modules_custom[num_aux_dirs_custom];
			for (n=0; n<strlen(aux_module_class_name); n++) {
				if (n >= MAX_LEN_CLASS_NAME-1) break;
				utfname_ptr[n] = aux_module_class_name[n];
			}
			utfname_ptr[n] = 0;

			dir = &(aux_dir[num_aux_dirs + num_aux_dirs_custom]);
			dir->name.ptr = utfname_ptr;
			dir->name.len = n * sizeof(CARD16);
			dir->method   = &xaux_so_methods;

			num_aux_dirs_custom ++;

			if (strcasecmp(ibml_category->scope, "binary"))
				continue;

			aux_module_file_path =  aux_dir_get_full_file_path(aux_module_object_file);
			if (aux_module_file_path == NULL)
				continue;

			strncpy(exec_aux_modules_custom[num_aux_classes_custom],
				aux_module_file_path,
				MAX_LEN_CLASS_NAME-1);
			free((char *)aux_module_file_path);

			class = &(xaux_classes[num_aux_classes + num_aux_classes_custom]);
			strncpy(classname_aux_modules_custom[num_aux_classes_custom],
				aux_module_class_name,
				MAX_LEN_CLASS_NAME-1);
			class->classname = classname_aux_modules_custom[num_aux_classes_custom];
			class->index = 0;
			class->extexec = exec_aux_modules_custom[num_aux_classes_custom];
			class->sowin = 0;
			class->clientwin = 0;
			class->utfname = utfname_ptr;
			
			num_aux_classes_custom ++;
		}
	}

	dir = &(aux_dir[num_aux_dirs + num_aux_dirs_custom]);
	dir->name.ptr = NULL;
	dir->name.len = 0;
	dir->method   = NULL;

	class = &(xaux_classes[num_aux_classes + num_aux_classes_custom]);
	class->classname = NULL;

	ibml_data_free(ibml_data);
	return (AUX_OK);
}

aux_dir_t *aux_dir_init()
{
	char *aux_dir_config_file = NULL;

	aux_dir_config_file =  aux_dir_get_full_file_path(XAUX_MODULES_FILE);

	if (aux_dir_config_file) {
		DEBUG_printf("aux_dir_config_file: %s\n", aux_dir_config_file);
		aux_dir_get_custom_aux_modules(aux_dir_config_file);
		free ((char *)aux_dir_config_file);
	}

#ifdef DEBUG
	aux_dir_print(aux_dir);
	aux_classes_print(xaux_classes);
#endif

	return (aux_dir);
}

#endif

// vi:ts=4:nowrap:cin:expandtab
